#include "config.h"

#include <rpc/rpc.h>

#define DBG_SUBSYS S_LIBINTERFACE

#include "fh.h"
#include "attr.h"
#include "nfs_state_machine.h"
#include "stat_cache.h"
#include "dbg.h"

/*
 * check whether stat_cache is for a regular file
 * fh_decomp must be called before to fill the stat cache
 */

int sattr_tomode(mode_t *mode, sattr *attr)
{
        if (attr->mode.set_it == TRUE)
                *mode = attr->mode.mode;
        else
                *mode = 0644;

        return 0;
}

/* compute post operation attributes given a stat buffer */
int get_postopattr_stat(post_op_attr *attr, struct stat *stbuf)
{
        attr->attr_follow = TRUE;

        if (S_ISDIR(stbuf->st_mode))
                attr->attr.type = NFS3_DIR;
        else if (S_ISBLK(stbuf->st_mode))
                attr->attr.type = NFS3_BLK;
        else if (S_ISCHR(stbuf->st_mode))
                attr->attr.type = NFS3_CHR;
        else if (S_ISLNK(stbuf->st_mode))
                attr->attr.type = NFS3_LNK;
        else if (S_ISSOCK(stbuf->st_mode))
                attr->attr.type = NFS3_SOCK;
        else if (S_ISFIFO(stbuf->st_mode))
                attr->attr.type = NFS3_FIFO;
        else
                attr->attr.type = NFS3_REG;

        attr->attr.mode = stbuf->st_mode & 0xFFFF;
        attr->attr.nlink = stbuf->st_nlink;
        attr->attr.uid = stbuf->st_uid;
        attr->attr.gid = stbuf->st_gid;
        attr->attr.size = stbuf->st_size;
        attr->attr.used = stbuf->st_blocks * FAKE_BLOCK;
        attr->attr.rdev.data1 = (stbuf->st_rdev >> 8) & 0xFF;
        attr->attr.rdev.data2 = stbuf->st_rdev & 0xFF;
        attr->attr.fsid = 2054;
        attr->attr.fileid = stbuf->st_ino;
        attr->attr.atime.seconds = stbuf->st_atime;
        attr->attr.atime.nseconds = 0;
        attr->attr.mtime.seconds = stbuf->st_mtime;
        attr->attr.mtime.nseconds = 0;
        attr->attr.ctime.seconds = stbuf->st_ctime;
        attr->attr.ctime.nseconds = 0;

        return 0;
}

void get_postopattr1(fileid_t *fileid, post_op_attr *attr)
{
        int ret;
        struct stat stbuf;

        DBUG("post op attr\n");

        ret = stor_getattr("default", fileid, &stbuf);
        if (unlikely(ret)) {
                attr->attr_follow = FALSE;
        } else {
                attr->attr_follow = TRUE;
                get_postopattr_stat(attr, &stbuf);
        }
}

void get_preopattr1(fileid_t *fileid, preop_attr *attr)
{
        int ret;
        struct stat stbuf;

        DBUG("pre op attr\n");

        ret = stor_getattr("default", fileid, &stbuf);
        if (unlikely(ret))
                attr->attr_follow = FALSE;
        else {
                attr->attr_follow = TRUE;

                attr->attr.size = stbuf.st_size;
                attr->attr.mtime.seconds = stbuf.st_mtime;
                attr->attr.mtime.nseconds = 0;
                attr->attr.ctime.seconds = stbuf.st_ctime;
                attr->attr.ctime.nseconds = 0;
        }
}
